package breakthrough.AlphaBetaPlayer.Evaluation;

import breakthrough.BreakthroughMove;
import breakthrough.BreakthroughState;

/**
 * Class used to hold the utility data and the associated move
 * 
 * @author oberliat
 */
public class ScoredBreakthroughState implements Comparable<ScoredBreakthroughState>{

	
	
	private double utility; // utility value of performing the given move
	private BreakthroughMove move; // the move to be made to retrieve this utility
	
	/**
	 * Creates a scored state by evaluating the given state and giving it a null move
	 * 
	 * @param board A BreakthroughState to be evaluated by the evaluation function
	 */
	public ScoredBreakthroughState(BreakthroughState board) {
		this.utility = this.evaluate(board);
		this.move = null;
	}
	
	/**
	 * Creates a dummy score state for use when trying to evaluate the alpha and the beta utilities
	 * Should almost always have a utility that is negative or positive infinity
	 * 
	 * @param utility A value to set the utility as
	 */
	public ScoredBreakthroughState(double utility) {
		this.utility = utility;
		this.move = null;
	}
	
	/**
	 * Evaluates a given board using several heuristics. Heuristics are listed in the classes enum Feature.
	 * The formula for the evaluation function is as follows:
	 * 				e(B) = sum(player_piece.value) - sum(opponent_piece) + player_extra_features - opponent_extra_features
	 * 
	 * @param board The BreakthroughState to evaluated
	 * @return A utility value for the given BreakthroughState
	 */
	private double evaluate(BreakthroughState board) {
		double whitePiecesSum = 0;
		double blackPiecesSum = 0;
		
		for (int i = 0; i < BreakthroughState.N; i++) {
			for (int j = 0; j < BreakthroughState.N; j++) {
				if (board.board[i][j] == BreakthroughState.homeSym) {
					EvaluatedPiece piece = new EvaluatedPiece(board, i, j, BreakthroughState.homeSym);
					whitePiecesSum += piece.getValue();
				}
				else if (board.board[i][j] != BreakthroughState.emptySym){
					EvaluatedPiece piece = new EvaluatedPiece(board, i, j, BreakthroughState.awaySym);
					blackPiecesSum += piece.getValue();
				}
			}
		}
		
		return whitePiecesSum - blackPiecesSum;
	}
	
	/**
	 * Retrieves the utility
	 * 
	 * @return utility for this given state
	 */
	public double getUtility() {
		return this.utility;
	}
	
	/**
	 * Sets the move of this state
	 * 
	 * @param move The BreakthroughMove to set this to
	 */
	public void setMove(BreakthroughMove move) {
		this.move = move;
	}
	
	/**
	 * Retrieves BreakthroughMove of this board
	 * 
	 * @return move of the given state
	 */
	public BreakthroughMove getMove() {
		return this.move;
	}
	
	/**
	 * Used to sort List of ScoredBreakthroughState items
	 * 
	 * @param scoredState The state to compare to
	 * @return sort value
	 */
	@Override
	public int compareTo(ScoredBreakthroughState scoredState) {
		if (this.getUtility() > scoredState.getUtility()) {
			return -1;
		}
		else if (this.getUtility() < scoredState.getUtility()) {
			return 1;
		}
		
		return 0;
	}
}
